// ==UserScript==
// @name         AI自动多轮对话工具
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  自动向AI逐次发送预设的对话内容，支持多轮对话
// @author       Trae
// @match        https://chat.deepseek.com/*
// @match        https://yuanbao.tencent.com/chat/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    /** 调试模式开关 */
    const DEBUG = false;

    /**
     * AI配置基类，定义所有AI平台通用的接口
     * @class
     */
    class AIConfig {
        /**
         * 创建AI配置实例
         * @param {string} name - AI平台名称
         */
        constructor(name) {
            this.name = name;
            this.lastConversationCounter = 0;
        }
        /**
         * 获取输入框元素
         * @returns {HTMLElement|null} 输入框元素或null
         */
        getInputElement() { return null; }
        /**
         * 获取对话列表
         * @returns {HTMLElement[]|null} 对话列表元素数组或null
         */
        getConversationList() { return null; }
        /**
         * 获取当前对话计数
         * @returns {number} 对话数量
         */
        getConversationCounter() {
            let conversationList = this.getConversationList();
            return conversationList ? conversationList.length : 0;
        }
        /**
         * 检查AI回复是否完成
         * @returns {boolean} 回复是否完成
         */
        isReplyCompleted() { return this.getConversationCounter() === this.lastConversationCounter; }
        /**
         * 检查是否可以发送下一条消息
         * @returns {boolean} 是否可以发送下一条消息
         */
        canSendNextMessage() {
            let currentConversationCounter = this.getConversationCounter();
            if (!currentConversationCounter || currentConversationCounter === this.lastConversationCounter) {
                return true;
            }
            let conversationList = this.getConversationList();
            // 检查conversationList是否为null或undefined
            if (!conversationList) {
                return true;
            }
            // （新增了一问一答） && （出现了操作按钮，说明AI已经完整输出了回复）  
            if (currentConversationCounter - this.lastConversationCounter === 2
                && this.isAIOutputOver(conversationList[conversationList.length - 1])) {
                this.lastConversationCounter = currentConversationCounter;
                return true;
            }
            return false;
        }
        /**
         * 检查AI输出是否完成（需要子类实现）
         * @param {HTMLElement} lastConversation - 最后一个对话元素
         * @returns {boolean} AI输出是否完成
         */
        isAIOutputOver(lastConversation) { return false; }
        /**
         * 在接收第一条消息前初始化对话计数
         */
        beforeReceiveFirstMessage() { this.lastConversationCounter = this.getConversationCounter(); }
        /**
         * 填充并发送消息
         * @param {string} message - 要发送的消息
         * @returns {Promise<boolean>} 发送是否成功
         */
        async fillAndSendMessage(message) { return false; }
        /**
         * 获取发送按钮
         * @returns {HTMLElement|null} 发送按钮元素或null
         */
        getSendButton() { return null; }
        /**
         * 发送消息
         * @returns {Promise<boolean>} 发送是否成功
         */
        async sendMessage() { return false; }
    }

    /**
     * DeepSeek AI平台配置类
     * @class
     * @extends AIConfig
     */
    class DeepSeekAIConfig extends AIConfig {
        /**
         * 创建DeepSeek AI配置实例
         */
        constructor() {
            super('DeepSeek');
        }
        /**
         * 获取DeepSeek输入框元素
         * @returns {HTMLTextAreaElement|null} 输入框元素或null
         */
        getInputElement() {
            return document.querySelector('textarea[placeholder="给 DeepSeek 发送消息 "]') ||
                document.querySelector('textarea');
        }
        /**
         * 获取DeepSeek对话列表
         * @returns {HTMLCollection|null} 对话列表元素集合或null
         */
        getConversationList() {
            const spanOpenNewConversation = document.evaluate("//span[text()='开启新对话']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(1);
            if (!spanOpenNewConversation) {
                debugLog('未找到开启新对话按钮');
                return null;
            }
            const lastConversationDiv = spanOpenNewConversation.parentElement.parentElement.previousElementSibling;
            return lastConversationDiv.children;
        }
        /**
         * 检查DeepSeek AI输出是否完成
         * @param {HTMLElement} lastConversation - 最后一个对话元素
         * @returns {boolean} AI输出是否完成
         */
        isAIOutputOver(lastConversation) {
            return lastConversation.children.length === 3;
        }
        /**
         * 创建输入框保护机制，防止文本被意外清空
         * @param {HTMLTextAreaElement} input - 输入框元素
         * @param {string} text - 要保护的文本内容
         * @returns {Object} 保护对象
         */
        createInputProtection(input, text) {
            const originalBlur = input.blur;
            const originalValue = input.value;
            const originalFocus = input.focus;

            // 创建保护对象，使用对象属性而不是闭包变量
            const protection = {
                isProtected: true,
                originalBlur,
                originalFocus,
                originalValue
            };

            // 重写blur方法
            input.blur = function () {
                if (protection.isProtected) {
                    debugLog('输入框blur被调用，但被阻止以防止文本清空');
                    return;
                }
                originalBlur.call(this);
            };

            // 重写focus方法以确保始终有焦点
            input.focus = function () {
                originalFocus.call(this);
                this.selectionStart = this.selectionEnd = this.value.length;
            };

            // 添加输入值保护
            Object.defineProperty(input, 'value', {
                get: function () {
                    return this._protectedValue || originalValue;
                },
                set: function (newValue) {
                    if (protection.isProtected && newValue === '') {
                        debugLog('检测到输入框值被清空，阻止此操作');
                        this._protectedValue = text;
                        const inputEvent = new Event('input', { bubbles: true, cancelable: true });
                        this.dispatchEvent(inputEvent);
                        return;
                    }
                    this._protectedValue = newValue;
                },
                configurable: true
            });

            return protection;
        }
        /**
         * 完成输入并清理保护机制
         * @param {HTMLTextAreaElement} input - 输入框元素
         * @param {Object} protection - 保护对象
         * @param {Function} resolve - Promise resolve函数
         */
        completeInputAndCleanup(input, protection, resolve) {
            debugLog('✅ 键盘模拟输入完成');
            debugLog('📝 最终值:', input.value);

            // 解除保护
            protection.isProtected = false;
            this.removeInputProtection(input, protection);

            // 触发所有必要的事件来确保发送按钮状态更新
            const finalEvents = ['input', 'change', 'blur', 'focus'];
            finalEvents.forEach(eventType => {
                const event = new Event(eventType, { bubbles: true, cancelable: true });
                input.dispatchEvent(event);
            });

            // 保持焦点，防止文字被清空
            input.focus();
            input.selectionStart = input.selectionEnd = input.value.length;

            resolve();
        }
        /**
         * 移除输入框保护机制
         * @param {HTMLTextAreaElement} input - 输入框元素
         * @param {Object} protection - 保护对象
         */
        removeInputProtection(input, protection) {
            input.blur = protection.originalBlur;
            input.focus = protection.originalFocus;
            Object.defineProperty(input, 'value', {
                get: function () {
                    return this._protectedValue || '';
                },
                set: function (newValue) {
                    this._protectedValue = newValue;
                },
                configurable: true
            });
        }
        /**
         * 触发键盘事件
         * @param {HTMLTextAreaElement} input - 输入框元素
         * @param {string} char - 字符
         */
        triggerKeyboardEvents(input, char) {
            const keyEvents = ['keydown', 'keypress', 'keyup'];
            keyEvents.forEach(eventType => {
                const event = new KeyboardEvent(eventType, {
                    key: char,
                    code: `Key${char.toUpperCase()}`,
                    keyCode: char.charCodeAt(0),
                    which: char.charCodeAt(0),
                    bubbles: true,
                    cancelable: true
                });
                input.dispatchEvent(event);
            });
        }
        /**
         * 触发中文输入法事件
         * @param {HTMLTextAreaElement} input - 输入框元素
         * @param {string} char - 字符
         */
        triggerCompositionEvents(input, char) {
            if (/[一-鿿]/.test(char)) {
                // 触发compositionstart
                const compStartEvent = new CompositionEvent('compositionstart', {
                    bubbles: true,
                    cancelable: true,
                    data: char
                });
                input.dispatchEvent(compStartEvent);

                // 触发compositionupdate
                const compUpdateEvent = new CompositionEvent('compositionupdate', {
                    bubbles: true,
                    cancelable: true,
                    data: char
                });
                input.dispatchEvent(compUpdateEvent);

                // 触发compositionend
                const compEndEvent = new CompositionEvent('compositionend', {
                    bubbles: true,
                    cancelable: true,
                    data: char
                });
                input.dispatchEvent(compEndEvent);
            }
        }
        /**
         * 填充并发送消息到DeepSeek
         * @param {string} message - 要发送的消息
         * @returns {Promise<boolean>} 发送是否成功
         */
        async fillAndSendMessage(message) {
            debugLog('fillAndSendMessage被调用，文本:', message);
            const input = this.getInputElement();
            if (!input) {
                debugLog('未找到输入框');
                updateStatus("未找到输入框");
                return false;
            }
            // 创建保护机制
            const protection = this.createInputProtection(input, message);

            // 清空输入框并设置焦点
            protection.isProtected = false;
            input.focus();
            input.value = '';
            input.selectionStart = input.selectionEnd = 0;
            protection.isProtected = true;

            // 触发清空事件
            const clearEvent = new Event('input', { bubbles: true, cancelable: true });
            input.dispatchEvent(clearEvent);

            debugLog('开始模拟键盘输入:', message);

            // 使用Promise包装的键盘模拟输入
            const typeTextWithKeyboardSimulation = () => {
                return new Promise((resolve) => {
                    let currentIndex = 0;

                    const typeNextChar = () => {
                        if (currentIndex >= message.length) {
                            this.completeInputAndCleanup(input, protection, resolve);
                            return;
                        }

                        const char = message[currentIndex];

                        // 强制保持焦点
                        input.focus();

                        // 获取当前光标位置
                        const startPos = input.selectionStart;
                        const endPos = input.selectionEnd;

                        // 在当前光标位置插入字符
                        input.value = input.value.substring(0, startPos) + char + input.value.substring(endPos);

                        // 更新光标位置
                        input.selectionStart = input.selectionEnd = startPos + 1;

                        // 触发键盘事件
                        this.triggerKeyboardEvents(input, char);

                        // 触发中文输入法事件
                        this.triggerCompositionEvents(input, char);

                        // 触发input事件
                        const inputEvent = new InputEvent('input', {
                            bubbles: true,
                            cancelable: true,
                            data: char,
                            inputType: 'insertText'
                        });
                        input.dispatchEvent(inputEvent);

                        currentIndex++;

                        // 使用setTimeout继续下一个字符，确保所有字符都能正确输入
                        if (currentIndex < message.length) {
                            setTimeout(typeNextChar, 50);
                        } else {
                            // 当输入完所有字符时，调用completeInputAndCleanup
                            this.completeInputAndCleanup(input, protection, resolve);
                        }
                    };

                    // 立即开始输入第一个字符
                    typeNextChar();
                });
            };

            try {
                // 等待键盘模拟输入完成
                await typeTextWithKeyboardSimulation();
                debugLog('当前输入框值（发送前）:', input.value);

                // 等待UI更新
                await wait(500);
                // 发送消息并等待发送完成
                const sendSuccess = await this.sendMessage();
                debugLog('消息发送结果:', sendSuccess);
                // 确保解除保护
                this.removeInputProtection(input, protection);

                return sendSuccess;
            } catch (error) {
                debugLog('键盘模拟输入过程中出错:', error);
                // 确保解除保护
                this.removeInputProtection(input, protection);
                return false;
            }
        }
        /**
         * 获取DeepSeek发送按钮
         * @returns {HTMLElement|null} 发送按钮元素或null
         */
        getSendButton() {
            const searchFromWebButton = document.evaluate(
                "//span[text()='联网搜索']",
                document,  // 上下文节点
                null,      // 命名空间解析器（无需时为null）
                XPathResult.FIRST_ORDERED_NODE_TYPE,  // 结果类型：第一个匹配节点
                null       // 现有结果（无需时为null）
            ).singleNodeValue;
            return searchFromWebButton ? searchFromWebButton.parentElement.parentElement.nextElementSibling.children[2] : null;
        }
        /**
         * 发送消息到DeepSeek
         * @returns {Promise<boolean>} 发送是否成功
         */
        async sendMessage() {
            const input = this.getInputElement();
            debugLog('sendMessage被调用，当前输入框值:', input ? input.value : '无输入框');

            if (!input || input.value.trim() === '') {
                debugLog('输入框为空或未找到，无法发送消息');
                return false;
            }

            // 确保输入框有焦点
            input.focus();
            input.selectionStart = input.selectionEnd = input.value.length;

            // 先触发input和change事件确保UI更新
            const inputEvent = new Event('input', { bubbles: true, cancelable: true });
            input.dispatchEvent(inputEvent);

            const changeEvent = new Event('change', { bubbles: true, cancelable: true });
            input.dispatchEvent(changeEvent);


            /*   
            debugLog('使用Enter键发送消息');
            // 触发完整的Enter键事件序列
            const enterEvents = ['keydown', 'keypress', 'keyup'];
            enterEvents.forEach(eventType => {
                const enterEvent = new KeyboardEvent(eventType, {
                    key: 'Enter',
                    code: 'Enter',
                    keyCode: 13,
                    which: 13,
                    bubbles: true,
                    cancelable: true,
                    composed: true,
                    // 添加更多标准属性
                    charCode: eventType === 'keypress' ? 13 : 0,
                    detail: 0,
                    view: window,
                    repeat: false
                });

                input.dispatchEvent(enterEvent);
            });
            */
            let sendButton = this.getSendButton();
            if (sendButton) {
                sendButton.click();
            }
            await wait(1000);
            debugLog('消息已发送');
            return true;
        }
    }
    /**
     * 元宝AI平台配置类
     * @class
     * @extends AIConfig
     */
    class YuanBaoAIConfig extends AIConfig {
        /**
         * 创建元宝AI配置实例
         */
        constructor() {
            super('YuanBao');
        }
        /**
         * 获取元宝AI输入框元素
         * @returns {HTMLElement|null} 输入框元素或null
         */
        getInputElement() {
            return document.querySelector('.ql-editor').querySelector('p');
        }
        /**
         * 获取元宝AI对话列表
         * @returns {NodeList|null} 对话列表元素集合或null
         */
        getConversationList() {
            return document.querySelectorAll('.agent-chat__list__item');
        }
        /**
         * 检查元宝AI输出是否完成
         * @param {HTMLElement} lastConversation - 最后一个对话元素
         * @returns {boolean} AI输出是否完成
         */
        isAIOutputOver(lastConversation) {
            let r = lastConversation.querySelector('.agent-chat__conv--ai__toolbar:not(.agent-chat__conv--ai__toolbar--loading)');
            //debugLog('isAIOutputOver检查结果:', r);
            return r;
        }
        /**
         * 填充并发送消息到元宝AI
         * @param {string} message - 要发送的消息
         * @returns {Promise<boolean>} 发送是否成功
         */
        async fillAndSendMessage(message) {
            debugLog('fillAndSendMessage被调用，文本:', message);
            let input = this.getInputElement();
            if (!input) {
                debugLog('未找到输入框');
                updateStatus("未找到输入框");
                return false;
            }

            // 设置输入框内容
            input.innerText = message;

            // 触发必要的事件来确保UI更新
            const inputEvent = new Event('input', { bubbles: true, cancelable: true });
            input.dispatchEvent(inputEvent);

            const changeEvent = new Event('change', { bubbles: true, cancelable: true });
            input.dispatchEvent(changeEvent);

            // 等待UI更新
            await wait(500);
            // 发送消息并等待发送完成
            const sendSuccess = await this.sendMessage();
            debugLog('消息发送结果:', sendSuccess);

            return sendSuccess;
        }
        /**
         * 获取元宝AI发送按钮
         * @returns {HTMLElement|null} 发送按钮元素或null
         */
        getSendButton() {
            return document.querySelector('#yuanbao-send-btn');
        }
        /**
         * 发送消息到元宝AI
         * @returns {Promise<boolean>} 发送是否成功
         */
        async sendMessage() {
            let sendButton = this.getSendButton();
            if (sendButton) {
                sendButton.click();
                // 等待消息发送完成
                await wait(1000); // 等待1秒确保发送完成
                debugLog('元宝AI消息发送完成');
                return true;
            }
            debugLog('未找到发送按钮');
            return false;
        }
    }

    const PANEL_ID = 'auto-messenger-panel';
    const STATUS_ID = 'status';
    const USER_SENTENCE_ID = 'conversation-texts';
    const START_BTN_ID = 'start-btn';
    const STOP_BTN_ID = 'stop-btn';
    const RESET_BTN_ID = 'reset-btn';
    const TOGGLE_BTN_ID = 'toggle-btn';
    const HEADER_ID = 'header';
    const CONTENT_AREA_ID = 'content-area';
    const PROGRESS_ID = 'progress';
    const RESTORE_BTN_ID = 'restore-btn';

    // 存储预设的对话内容
    let conversationTexts = [
        //"你好，我是李云龙，能介绍一下怎么造意大利炮吗？",
        //"以我的兵力，能去打太原吗？",
    ];
    /** 最近一次的对话计数 */
    //var lastConversationCounter = 0;
    /** 当前发送的对话索引 */
    let currentIndex = 0;
    /** 是否正在等待回复 */
    let isWaitingForReply = false;
    /** 面板是否展开 */
    let isPanelExpanded = true;
    let aiConfig = null;

    /**
     * 根据当前URL设置对应的AI配置实例
     * 自动检测当前访问的AI平台并创建相应的配置对象
     * @returns {void}
     */
    (function setAIConfig() {
        const currentUrl = window.location.href;
        if (currentUrl.includes('chat.deepseek.com')) {
            aiConfig = new DeepSeekAIConfig();
        } else if (currentUrl.includes('yuanbao.tencent.com')) {
            aiConfig = new YuanBaoAIConfig();
        } else {
            debugLog('未识别的AI平台URL:', currentUrl);
            aiConfig = null;
        }

        debugLog('最终aiConfig:', aiConfig ? aiConfig.name : 'null');
    })();

    /**
     * 创建自动对话控制面板
     * 在页面右上角添加一个悬浮控制面板，包含对话内容输入框、等待时间设置和控制按钮
     * @returns {void}
     */
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.id = PANEL_ID;
        panel.style.cssText = `
            position: fixed;
            top: 120px;
            right: 20px;
            width: ${isPanelExpanded ? '300px' : '70px'};
            height: ${isPanelExpanded ? 'auto' : '40px'};
            background: white;
            border: 1px solid #ccc;
            border-radius: 8px;
            padding: ${isPanelExpanded ? '15px' : '5px'};
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            z-index: 9999;
            transition: all 0.3s ease;
            overflow: hidden;
        `;

        panel.innerHTML = `
            <div id="${HEADER_ID}" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: ${isPanelExpanded ? '10px' : '0'};">
                <h3 style="margin: 0; color: #333; font-size: 14px;">AI自动对话工具</h3>
                <button id="${TOGGLE_BTN_ID}" style="background: none; border: none; cursor: pointer; font-size: 12px; color: #007bff; text-decoration: underline;">
                    ${isPanelExpanded ? '收起面板' : '展开面板'}
                </button>
            </div>
            <div id="${PROGRESS_ID}" style="font-size: 12px; color: #666; margin-bottom: 5px; display: ${isPanelExpanded ? 'none' : 'block'};">
                进度: 0/${conversationTexts.length}
            </div>
            <button id="${RESTORE_BTN_ID}" style="background: none; border: none; cursor: pointer; font-size: 12px; color: #007bff; text-decoration: underline; display: ${isPanelExpanded ? 'none' : 'block'};">
                展开面板
            </button>
            <div id="${CONTENT_AREA_ID}" style="display: ${isPanelExpanded ? 'flex' : 'none'}; flex-direction: column;">
                <div style="margin-bottom: 10px;">
                    <label style="display: block; margin-bottom: 5px;">对话内容（每行一条）：</label>
                    <textarea id="${USER_SENTENCE_ID}" rows="6" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">${conversationTexts.join('\n')}</textarea>
                </div>
                <div style="display: flex; gap: 10px;">
                    <button id="${START_BTN_ID}" style="flex: 1; padding: 8px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">开始发送</button>
                    <button id="${STOP_BTN_ID}" style="flex: 1; padding: 8px; background: #dc3545; color: white; border: none; border-radius: 4px; cursor: pointer; display: none;">停止</button>
                    <button id="${RESET_BTN_ID}" style="padding: 8px; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;">重置</button>
                </div>
                <div id="${STATUS_ID}" style="margin-top: 10px; color: #666; font-size: 12px;">状态：未开始</div>
            </div>
        `;

        document.body.appendChild(panel);

        // 绑定按钮事件
        document.getElementById(START_BTN_ID).addEventListener('click', startSending);
        document.getElementById(STOP_BTN_ID).addEventListener('click', stopSending);
        document.getElementById(RESET_BTN_ID).addEventListener('click', resetConversation);
        document.getElementById(TOGGLE_BTN_ID).addEventListener('click', togglePanel);
        document.getElementById(RESTORE_BTN_ID).addEventListener('click', togglePanel);
    }

    /**
     * 切换面板展开/收缩状态
     * 控制控制面板的显示状态切换，更新相关UI元素的可见性
     * @returns {void}
     */
    function togglePanel() {
        isPanelExpanded = !isPanelExpanded;
        const panel = document.getElementById(PANEL_ID);
        const headerDiv = document.getElementById(HEADER_ID);
        const toggleBtn = document.getElementById(TOGGLE_BTN_ID);
        const contentDiv = document.getElementById(CONTENT_AREA_ID);
        const progressDiv = document.getElementById(PROGRESS_ID);
        const restoreBtn = document.getElementById(RESTORE_BTN_ID);

        panel.style.width = isPanelExpanded ? '300px' : '70px';
        panel.style.height = isPanelExpanded ? 'auto' : '40px';
        toggleBtn.textContent = isPanelExpanded ? '收起面板' : '展开面板';
        headerDiv.style.display = contentDiv.style.display = isPanelExpanded ? 'flex' : 'none';
        progressDiv.style.display = restoreBtn.style.display = isPanelExpanded ? 'none' : 'block';

        // 更新进度显示
        updateProgress();
    }

    /**
     * 更新进度显示
     * 根据当前发送进度和对话完成状态更新进度显示文本
     * @returns {string} 更新后的进度文本
     */
    function updateProgress() {
        const progressDiv = document.getElementById(PROGRESS_ID);
        if (progressDiv) {
            if (currentIndex >= conversationTexts.length
                && conversationTexts.length > 0
                && aiConfig.isReplyCompleted()) {
                progressDiv.textContent = '对话完成';
            } else {
                progressDiv.textContent = `进度: ${currentIndex}/${conversationTexts.length}`;
            }
            return progressDiv.textContent;
        }
        return '';
    }

    /**
     * 更新控制面板的状态显示
     * 设置控制面板底部状态区域的显示文本
     * @param {string} text - 要显示的状态文本
     * @returns {void}
     */
    function updateStatus(text) {
        const statusDiv = document.getElementById(STATUS_ID);
        if (statusDiv) {
            statusDiv.textContent = `状态：${text}`;
        }
    }

    /**
     * 开始自动发送消息序列
     * 从文本区域读取对话内容，初始化状态，并开始发送第一条消息
     * @returns {void}
     */
    function startSending() {
        // 更新对话内容
        const textarea = document.getElementById(USER_SENTENCE_ID);
        conversationTexts = textarea.value.split('\n').filter(text => text.trim() !== '');

        if (conversationTexts.length === 0) {
            alert('请输入对话内容');
            return;
        }
        // 更新UI状态
        document.getElementById(START_BTN_ID).style.display = 'none';
        document.getElementById(STOP_BTN_ID).style.display = 'block';
        currentIndex = 0;
        updateStatus('开始发送消息...');
        updateProgress(); // 更新进度显示
        // 先计算发消息前已经有多少条对话
        aiConfig.beforeReceiveFirstMessage();
        // 发送第一条消息
        sendNextMessage();
    }

    /**
     * 发送序列中的下一条消息
     * 自动处理消息索引递增和定时器设置
     * @returns {void}
     */
    async function sendNextMessage() {
        debugLog('sendNextMessage被调用，当前索引:', currentIndex, '总消息数:', conversationTexts.length);

        if (currentIndex >= conversationTexts.length) {
            debugLog('所有消息已发送完毕');
            updateProgress(); // 更新进度显示为"对话完成"
            updateStatus('所有消息已发送完毕');
            stopSending(true);
            await waitUntil(() => aiConfig.canSendNextMessage(), 250);
            updateProgress();
            return;
        }

        // 发送当前消息
        debugLog('准备发送消息:', conversationTexts[currentIndex]);
        await waitUntil(() => aiConfig.canSendNextMessage(), 250);
        const success = await aiConfig.fillAndSendMessage(conversationTexts[currentIndex]);
        debugLog(`消息${conversationTexts[currentIndex]}发送结果:`, success);
        if (!success) {
            debugLog(`消息${conversationTexts[currentIndex]}发送失败，停止发送`);
            stopSending();
            return;
        }

        currentIndex++;
        isWaitingForReply = true;
        let status = updateProgress(); // 更新进度显示
        updateStatus(`等待回复完成后发送下一条，${status}`);
        if (!isWaitingForReply) {
            debugLog('已停止，无需发送下一条消息');
            return;
        }
        // 发送消息的最小间隔
        await wait(3000);
        // 回复完成后发送下一条消息
        return sendNextMessage();
    }

    /**
     * 停止自动发送过程
     * 清除定时器，重置状态，恢复UI到初始状态
     * @param {boolean} [isNormalStop=false] - 是否为正常停止（完成所有消息发送）
     * @returns {void}
     */
    function stopSending(isNormalStop = false) {
        isWaitingForReply = false;
        document.getElementById(START_BTN_ID).style.display = 'block';
        document.getElementById(STOP_BTN_ID).style.display = 'none';
        if (!isNormalStop) {
            updateStatus('已停止');
        }
        updateProgress(); // 更新进度显示
        debugLog('自动发送已停止');
    }

    // 重置对话
    /**
     * 重置对话状态
     * 停止发送并将当前索引重置为0
     * @returns {void}
     */
    function resetConversation() {
        stopSending();
        currentIndex = 0;
        updateStatus('已重置');
        updateProgress(); // 更新进度显示
    }

    // 页面加载完成后初始化
    window.addEventListener('load', function () {
        //console.log('页面加载完成，准备创建控制面板');
        // 延迟初始化，确保页面完全加载
        setTimeout(function () {
            if (!document.getElementById(PANEL_ID)) {
                createControlPanel();
            }
        }, 2000);
    });

    // 监控页面变化，处理单页应用路由变化
    const observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            if (mutation.addedNodes.length) {
                //console.log('检查是否已经有控制面板，如果没有则创建');
                if (!document.getElementById(PANEL_ID)) {
                    createControlPanel();
                }
            }
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });


    /**
     * 等待直到条件满足
     * @param {Function} testCondition - 测试条件函数
     * @param {number} checkIntervalMillisecond - 检查间隔毫秒数
     * @returns {Promise<number>} 等待完成的Promise
     */
    function waitUntil(testCondition, checkIntervalMillisecond) {
        return new Promise(resolve => {
            let id = setInterval(() => {
                if (testCondition()) {
                    clearInterval(id);
                    resolve(0);
                }
            }, checkIntervalMillisecond);
        });
    }
    /**
     * 等待指定毫秒数
     * @param {number} millisecond - 等待的毫秒数
     * @returns {Promise<void>} 等待完成的Promise
     */
    function wait(millisecond) {
        return new Promise(resolve => setTimeout(resolve, millisecond));
    }

    /**
     * 自定义日志函数
     * @param {...any} args - 要记录的参数
     */
    function debugLog(...args) {
        if (!DEBUG) {
            console.log(...args);
        } else {
            // 同时输出到文件（在用户脚本环境中有限制，这里使用GM_xmlhttpRequest需要@grant权限）
            // 作为替代方案，我们可以将日志存储在localStorage中
            try {
                const timestamp = new Date().toISOString();
                const logMessage = `[${timestamp}] ${args.map(arg =>
                    typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
                ).join(' ')}`;

                // 保存到localStorage
                const existingLogs = localStorage.getItem('aiMessengerDebugLogs') || '';
                const newLogs = existingLogs + logMessage + '\n';

                // 限制日志大小，只保留最近1000行
                const logsArray = newLogs.split('\n');
                if (logsArray.length > 1000) {
                    logsArray.splice(0, logsArray.length - 1000);
                }

                localStorage.setItem('aiMessengerDebugLogs', logsArray.join('\n'));
            } catch (e) {
                console.error('日志保存失败:', e);
            }
        }
    }
})();